package ar.com.larreta.colegio.entidades;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

import ar.com.larreta.comunes.Propiedades;
import ar.com.larreta.entidades.Entidad;
import ar.com.larreta.procesos.AdministradorDeProcesos;
import ar.com.larreta.utilidades.UtilidadesNumeros;

@Entity
@Table(name = "detalle")
// Borrado logico
@SQLDelete (sql="UPDATE Detalle SET fechaEliminacion=CURRENT_TIMESTAMP WHERE ID=?")
// Solamente trae los que no fueron borrados logicamente
@Where(clause="fechaEliminacion IS NULL")
public class Detalle extends Entidad implements Comparable<Detalle> {

	public static final String FORMATO_NUMERICO = "formato.numerico";
	public static final String SIMBOLO_MONETARIO = "simbolo.monetario";
	
	private Long id;
	private String nombre;
	private Double valor;
	private Set<DetalleEspecifico> detallesEspecificos;
	private Obligacion obligacion;
	
	@ManyToOne (fetch=FetchType.LAZY)
	@JoinColumn (name="idObligacion")	
	public Obligacion getObligacion() {
		return obligacion;
	}

	public void setObligacion(Obligacion obligacion) {
		this.obligacion = obligacion;
	}
	
	@Transient
	public JRDataSource getDetallesEspecificosDataSource(){
		List detallesEspecificos = new ArrayList(getDetallesEspecificos());
		Collections.sort(detallesEspecificos);
		return new JRBeanCollectionDataSource(detallesEspecificos);
	}

	@OneToMany (mappedBy="detalle", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
	// Solamente trae los que no fueron borrados logicamente
	@Where(clause="fechaEliminacion IS NULL")
	public Set<DetalleEspecifico> getDetallesEspecificos() {
		return detallesEspecificos;
	}

	public void setDetallesEspecificos(Set<DetalleEspecifico> detallesEspecificos) {
		if (detallesEspecificos!=null){
			Date fechaActual = new Date();
			Iterator<DetalleEspecifico> iterator = detallesEspecificos.iterator();
			while (iterator.hasNext()) {
				DetalleEspecifico detalle = (DetalleEspecifico) iterator.next();
				detalle.setDetalle(this);
				detalle.setFechaCreacion(fechaActual);
			}
		}
		this.detallesEspecificos = detallesEspecificos;
	}

	@Id @GeneratedValue(strategy=GenerationType.AUTO)
	public Long getId() {
		return id;
	}
	
	public void setId(Long id) {
		this.id = id;
	}
	
	@Basic @Column (name="nombre")
	public String getNombre() {
		return nombre;
	}
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	
	@Transient
	public String getValorConFormato(){
		if (valor==null){
			return StringUtils.EMPTY;
		}
		Propiedades propiedadesDeConfiguracionDeLaAplicacion = AdministradorDeProcesos.getInstancia(null).getPropiedades();
		return propiedadesDeConfiguracionDeLaAplicacion.getProperty(SIMBOLO_MONETARIO) + 
				UtilidadesNumeros.transformarNumeroATexto(valor, propiedadesDeConfiguracionDeLaAplicacion.getProperty(FORMATO_NUMERICO));
	}
	
	@Basic @Column (name="valor")
	public Double getValor() {
		if ((detallesEspecificos!=null) && (!detallesEspecificos.isEmpty())){
			Double valorTmp = new Double(0);
			Iterator<DetalleEspecifico> it = detallesEspecificos.iterator();
			while (it.hasNext()) {
				DetalleEspecifico detalleEspecifico = (DetalleEspecifico) it.next();
				if (detalleEspecifico.getValor()!=null){
					valorTmp+=detalleEspecifico.getValor();
				}
			}
			if ((valorTmp!=null) && (valorTmp>0)){
				valor = valorTmp;
			}
		}
		return valor;
	}
	
	public void setValor(Double valor) {
		this.valor = valor;
	}

	public int compareTo(Detalle detalle) {
		return this.nombre.compareTo(detalle.getNombre());
	}

}
